package com.zhongxi.guoyuan.utils;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.util.Xml;

import com.alipay.sdk.app.PayTask;
import com.tencent.mm.sdk.modelpay.PayReq;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;
import com.zhongxi.guoyuan.R;
import com.zhongxi.guoyuan.application.MyApplication;
import com.zhongxi.guoyuan.entity.pay.PayAliPayData;
import com.zhongxi.guoyuan.entity.pay.WeixinData;
import com.zhongxi.guoyuan.url.Url;
import com.zhongxi.guoyuan.view.PaySuccessActivity;
import com.zhongxi.guoyuan.view.QrOrderActivity;
import com.zhongxi.guoyuan.view.beautifulStore.OrderActivity;
import com.zhongxi.guoyuan.weixin.MD5;
import com.zhongxi.guoyuan.weixin.Util;
import com.zhongxi.guoyuan.zhifubao.PayResult;
import com.zhongxi.guoyuan.zhifubao.SignUtils;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.xmlpull.v1.XmlPullParser;

import java.io.StringReader;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * Created by Administrator on 2018/2/28.
 */

public class PayUtils {

    private String orderId;
    private String name;
    private int type;
    private String innerprice;
    private String redbean;
    private String price;

    /***
     *
     * @param orderId     订单id
     * @param name        商品名称
     * @param type        支付类型
     * @param innerprice  支付美豆数
     * @param redbean     实际支付红豆数
     * @param price       时间支付价钱
     */
    public PayUtils(String orderId, String name, int type, String innerprice, String redbean, String price) {
        this.orderId = orderId;
        this.name = name;
        this.type = type;
        this.innerprice = innerprice;
        this.redbean = redbean;
        this.price = price;
    }

    /**
     * 支付宝支付
     *
     * @param alipay
     */
    public void zhifubaoPay(PayAliPayData alipay, final Handler mHandler, final Activity activity) {

        String orderInfo = getOrderInfo(alipay);

        //  特别注意，这里的签名逻辑需要放在服务端，切勿将私钥泄露在代码中

        String sign = sign(orderInfo, alipay.getRsaPrivate());
        try {
            //仅需对sign做URL编码
            sign = URLEncoder.encode(sign, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        //完整的符合支付宝参数规范的订单信息
        final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();

        Runnable payRunnable = new Runnable() {
            @Override
            public void run() {
                // 构造PayTask 对象
                PayTask alipay = new PayTask(activity);
                // 调用支付接口，获取支付结果
                String result = alipay.pay(payInfo, true);

                Message msg = new Message();
                msg.what = 0;
                msg.obj = result;
                mHandler.sendMessage(msg);
            }
        };

        // 必须异步调用
        Thread payThread = new Thread(payRunnable);
        payThread.start();

    }

    private String getOrderInfo(PayAliPayData alipay) {
        String trade = "";
        if ((orderId + genOutTradNo()).length() > 32) {
            trade = (orderId + genOutTradNo()).substring(0, 32);
        } else {
            trade = orderId + genOutTradNo();
        }

        // 签约合作者身份ID
        String orderInfo = "partner=" + "\"" + alipay.getPartner() + "\"";

        // 签约卖家支付宝账号
        orderInfo += "&seller_id=" + "\"" + alipay.getSeller() + "\"";

        // 商户网站唯一订单号
        orderInfo += "&out_trade_no=" + "\"" + trade + "\"";

        orderInfo += "&subject=" + "\"" + name + "\"";
        if (type == 2) {
            // 商品详情线下扫码支付
            orderInfo += "&body=" + "\"" + getTimeValue() + "||" + MyApplication.getInstance().getUserId() + "||"
                    + orderId + "||" + type + "||" + price + "\"";
        } else {
            // 商品详情 美豆兑换支付
            orderInfo += "&body=" + "\"" + getTimeValue() + "||" + MyApplication.getInstance().getUserId() + "||"
                    + orderId + "||" + type + "||" + innerprice + "," + redbean + "," + price + "\"";
        }

        //mtf84445a25f3d559320
        // 商品金额
        orderInfo += "&total_fee=" + "\"" + price + "\"";

        // 服务器异步通知页面路径
        orderInfo += "&notify_url=" + "\"" + Url.BASE_URL + "/notify/pay/alipay" + "\"";

        // 服务接口名称， 固定值
        orderInfo += "&service=\"mobile.securitypay.pay\"";

        // 支付类型， 固定值
        orderInfo += "&payment_type=\"1\"";

        // 参数编码， 固定值
        orderInfo += "&_input_charset=\"utf-8\"";

        // 设置未付款交易的超时时间
        // 默认30分钟，一旦超时，该笔交易就会自动被关闭。
        // 取值范围：1m～15d。
        // m-分钟，h-小时，d-天，1c-当天（无论交易何时创建，都在0点关闭）。
        // 该参数数值不接受小数点，如1.5h，可转换为90m。
        orderInfo += "&it_b_pay=\"30m\"";

        // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
        // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";

        // 支付宝处理完请求后，当前页面跳转到商户指定页面的路径，可空
        orderInfo += "&return_url=\"" + Url.BASE_URL + "\"";
        return orderInfo;
    }

    /**
     * sign the order info. 对订单信息进行签名（支付宝）
     *
     * @param content 待签名订单信息
     */
    private String sign(String content, String rsa_private) {
        return SignUtils.sign(content, rsa_private);
    }

    /**
     * get the sign type we use. 获取签名方式（支付宝）
     */
    private String getSignType() {
        return "sign_type=\"RSA\"";
    }

    private String genOutTradNo() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }

    /**
     * 获取当前时间戳
     *
     * @return
     */
    private String getTimeValue() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String str = sdf.format(date);
        return str;
    }

    private IWXAPI msgApi;
    private PayReq req;
    private StringBuffer sb;
    private Map<String, String> resultunifiedorder;
    private Context context;
    private   WeixinData wechat;

    public PayUtils(String orderId, String name, int type, String innerprice, String redbean, String price, Context context, WeixinData wechat) {
        this.orderId = orderId;
        this.name = name;
        this.type = type;
        this.innerprice = innerprice;
        this.redbean = redbean;
        this.price = price;
        this.context = context;
        this.wechat = wechat;
    }

    public void weixinPay() {
        msgApi = WXAPIFactory.createWXAPI(context, wechat.getAppid());
        // 将该app注册到微信
        msgApi.registerApp(wechat.getAppid());
        getWXOrderInfo();
    }

    /**
     * 获取微信支付订单
     */
    private void getWXOrderInfo() {
        //正常情况下，请求服务器获取订单参数
        req = new PayReq();
        sb = new StringBuffer();
        GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
        getPrepayId.execute();
    }


    private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {

        private ProgressDialog dialog;

        @Override
        protected void onPreExecute() {
            dialog = ProgressDialog.show(context,context.getString(R.string.app_tip) , context.getString(R.string.getting_prepayid));
        }

        @Override
        protected void onPostExecute(Map<String, String> result) {
            if (dialog != null) {
                dialog.dismiss();
            }
            sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");
            resultunifiedorder = result;
            genPayReq();
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
        }

        @Override
        protected Map<String, String> doInBackground(Void... params) {

            String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
            String entity = genProductArgs();
            byte[] buf = Util.httpPost(url, entity);

            String content = new String(buf);
            Log.e("orion", content);
            Map<String, String> xml = decodeXml(content);

            return xml;
        }

    }

    private void genPayReq() {

        req.appId = wechat.getAppid();
        req.partnerId = wechat.getSeller();
        req.prepayId = resultunifiedorder.get("prepay_id");
        req.packageValue = "Sign=WXPay";
        req.nonceStr = genNonceStr();
        req.timeStamp = String.valueOf(genTimeStamp());


        List<NameValuePair> signParams = new LinkedList<NameValuePair>();
        signParams.add(new BasicNameValuePair("appid", req.appId));
        signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
        signParams.add(new BasicNameValuePair("package", req.packageValue));
        signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
        signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
        signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));

        req.sign = genAppSign(signParams);

        sb.append("sign\n" + req.sign + "\n\n");

//        showShortToast("sb:"+sb.toString());
        Log.e("orion", signParams.toString());

        msgApi.sendReq(req);

    }

    private String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }

    private long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }

    private String genAppSign(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(wechat.getPartner());

        this.sb.append("sign str\n" + sb.toString() + "\n\n");
        String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        Log.e("orion", appSign);
        return appSign;
    }

    /**
     * 生成签名（微信）
     */

    private String genPackageSign(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(wechat.getPartner());

        String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        Log.e("orion", packageSign);
        return packageSign;
    }



    private String genProductArgs() {
        StringBuffer xml = new StringBuffer();
        try {
            String nonceStr = genNonceStr();
            String trade = "";
            if ((orderId + genOutTradNo()).length() > 32) {
                trade = (orderId + genOutTradNo()).substring(0, 32);
            } else {
                trade = orderId + genOutTradNo();
            }
            xml.append("</xml>");
            List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
            packageParams.add(new BasicNameValuePair("appid", wechat.getAppid()));
            if (type==2){
                packageParams.add(new BasicNameValuePair("attach", getTimeValue() + "||" + MyApplication.getInstance().getUserId() + "||"
                        + orderId + "||"+type+"||"  + price));
            }else {
                packageParams.add(new BasicNameValuePair("attach", getTimeValue() + "||" + MyApplication.getInstance().getUserId() + "||"
                        + orderId + "||"+type+"||"  + innerprice + "," + redbean + "," +price));
            }
            packageParams.add(new BasicNameValuePair("body", name));
            packageParams.add(new BasicNameValuePair("mch_id", wechat.getSeller()));
            packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
            packageParams.add(new BasicNameValuePair("notify_url", Url.BASE_URL + "/notify/pay/wepay"));
            packageParams.add(new BasicNameValuePair("out_trade_no", trade));
            packageParams.add(new BasicNameValuePair("spbill_create_ip", MyApplication.getInstance().getLocalIPAddress()));
            packageParams.add(new BasicNameValuePair("total_fee", new BigDecimal(price).multiply(new BigDecimal(100)).intValue() + ""));
            packageParams.add(new BasicNameValuePair("trade_type", "APP"));

            String sign = genPackageSign(packageParams);
            packageParams.add(new BasicNameValuePair("sign", sign));

            String xmlstring = toXml(packageParams);

            Log.i("base", xmlstring);
            return new String(xmlstring.toString().getBytes(), "ISO8859-1");

        } catch (Exception e) {
            Log.e("base", "" + e.getMessage());
            return null;
        }
    }

    private String toXml(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (int i = 0; i < params.size(); i++) {
            sb.append("<" + params.get(i).getName() + ">");


            sb.append(params.get(i).getValue());
            sb.append("</" + params.get(i).getName() + ">");
        }
        sb.append("</xml>");

        Log.e("orion", sb.toString());
        return sb.toString();
    }

    public Map<String, String> decodeXml(String content) {
        try {
            Map<String, String> xml = new HashMap<String, String>();
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new StringReader(content));
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {

                String nodeName = parser.getName();
                switch (event) {
                    case XmlPullParser.START_DOCUMENT:
                        break;
                    case XmlPullParser.START_TAG:

                        if ("xml".equals(nodeName) == false) {
                            //实例化student对象
                            xml.put(nodeName, parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        break;
                }
                event = parser.next();
            }
            return xml;
        } catch (Exception e) {
            Log.e("orion", e.toString());
        }
        return null;
    }

}
